/*******************************************************************************
 * Copyright (c) 2007 University of Oslo.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     University of Oslo - initial API and implementation
 *******************************************************************************/

package com.cea.papyrus.diagram.sequence.sedi.edit.handlers;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.commands.Command;
import org.eclipse.uml2.uml.InteractionFragment;

import com.cea.papyrus.core.utils.LookForElement;
import com.cea.papyrus.diagram.sequence.sedi.edit.FrameEditPart;
import com.cea.papyrus.diagram.sequence.sedi.edit.command.AnalyseBestCoveredCommand;
import com.cea.papyrus.diagram.sequence.sedi.edit.command.AnalyseOwnerCommand;
import com.cea.papyrus.diagram.sequence.sedi.edit.command.DecideStopBoundsCommand;
import com.cea.papyrus.diagram.sequence.sedi.model.command.CoverCommand;
import com.cea.papyrus.diagram.sequence.sedi.model.command.LifelinePosition;
import com.cea.papyrus.diagram.sequence.sedi.model.command.SetConstraintCommand;
import com.cea.papyrus.diagram.sequence.sedi.model.command.SetOwnerCommand;
import com.cea.papyrus.diagram.sequence.sedi.model.util.ModelUtil;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;

/**
 * Handles layout of Stops (OccurrenceSpecifications which references DestructionEvents).
 * 
 * @author frankd@ifi.uio.no
 */
public class StopLayoutHandler extends InteractionFragmentLayoutHandler {


    @SuppressWarnings("unchecked")
    public Command[] getMoveCommands(final EditPart fragmentPart, final Rectangle suggestedBounds) {

        // AnalyseBestCoveredByCommand
        // DecideStopBoundsCommand
        // CoverCommand
        // Moving the fragment may have brought a different lifeline
        // beneath it.
        // SetConstraintCommand TODO should be derivable from model event
        // AnalyseOwnerCommand
        // SetOwnerCommand

        final GraphNode fragmentView = (GraphNode) fragmentPart.getModel();

        final InteractionFragment fragment =
                ModelUtil.<InteractionFragment> getSemantic(fragmentView);

        final AnalyseBestCoveredCommand analyseCoveredCmd = new AnalyseBestCoveredCommand();
        analyseCoveredCmd.setInteractionEditPart((FrameEditPart) fragmentPart.getParent());
        analyseCoveredCmd.setFragmentNode(fragmentView);
        analyseCoveredCmd.setBounds(suggestedBounds);
    	
        final DecideStopBoundsCommand decideBoundsCmd = new DecideStopBoundsCommand();
        decideBoundsCmd.setAnyEditPart(fragmentPart);
        // glue1: lifeline from analyseCoveredCmd

        final CoverCommand coverCmd = new CoverCommand();        
        coverCmd.setFragment(fragment);
        // glue1: covered from analyseCoveredCmd

    	if (!isDetachedFromLifeline()) {
    		
        	decideBoundsCmd.setLifeline(fragment.getCovereds().get(0));
        	LifelinePosition coveredLifelinePosition = 
        		new LifelinePosition(fragment.getCovereds().get(0), 0);
        	List<LifelinePosition>  lifelinePositions = 
        		new ArrayList<LifelinePosition>();
        	lifelinePositions.add(coveredLifelinePosition);
        	coverCmd.setCovered(lifelinePositions);
        	
    	}
    	
        final SetConstraintCommand setBoundsCmd = new SetConstraintCommand();
        setBoundsCmd.setElement(fragmentView);
        // glue2: location from decideBoundsCmd

        final AnalyseOwnerCommand analyseOwnerCmd = new AnalyseOwnerCommand();
        analyseOwnerCmd.setAnyEditPart(fragmentPart);
        analyseOwnerCmd.setDiagram(LookForElement.getDiagram(fragmentView));
        // glue2: location from decideBoundsCmd

        final SetOwnerCommand setOwnerCmd = new SetOwnerCommand();
        setOwnerCmd.setFragment(fragment);
        // glue3: owner

        final Command glue1 = new Command() {
            public void execute() {
            	if (isDetachedFromLifeline()) {
            		            		
                	final List<LifelinePosition> list = analyseCoveredCmd.getCovered();
                	coverCmd.setCovered(list);
                	assert (!list.isEmpty());
                	decideBoundsCmd.setLifeline(list.get(0).getLifeline());
            	}
            }
        };

        final Command glue2 = new Command() {
            public void execute() {
                analyseOwnerCmd.setLocation(decideBoundsCmd.getPreferredBounds().getLocation());
                setBoundsCmd.setBounds(decideBoundsCmd.getPreferredBounds());
            }
        };

        final Command glue3 = new Command() {
            public void execute() {
                setOwnerCmd.setOwner(analyseOwnerCmd.getOwner());
            }
        };

        if (isDetachedFromLifeline()) {
            return new Command[] {
                    analyseCoveredCmd, glue1, 
                    decideBoundsCmd, 
                    coverCmd, glue2, 
                    setBoundsCmd,
                    analyseOwnerCmd, glue3, 
                    setOwnerCmd};
        } else {
            return new Command[] { 
                    decideBoundsCmd, 
                    coverCmd, glue2, 
                    setBoundsCmd,
                    analyseOwnerCmd, glue3, 
                    setOwnerCmd};
        }
    }
}
